//! stage.rs
//! Stage是一场沙盒环境的生命周期(舞台)
//! 当并发多个Stages时, 不同的Stage负责不同的平行线
//! 多个Stage之间是并行且互不关联的, 品种可能也会略微区别
//! 该Stage DTO用于描述一个交易撮合Stage的状态和配置
//! 配置包括手续费/时间倍率等回测相关参数
//! Server端会根据Stage的配置id生成 /wt/{stage_id} 的后台任务
#![allow(unused_imports)]
use serde::{Deserialize, Serialize};
use serde_json;
use chrono::prelude::*;
use std::hash::{Hash, Hasher};

// 定义Stage类型
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "UPPERCASE")]
pub enum StageType {
    SIM,    // 模拟环境(通过eztrade-core交易所机制计算撮合结果)
    CTP,    // CTP环境(通过CTP接口进行撮合)
}

// 定义Stage的生命周期阶段
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum StagePhase{
    Created,          // 已创建
    Initializing,     // 初始化中(缓存数据, 等待订阅等)
    Running,          // 正在运行(按照时间倍率模拟中)
    Paused,           // 已暂停(通过指令暂停和恢复, 暂停只是时间倍率变为1, 当超时会自动恢复)
    Closed,           // 已关闭/休市中(不再接收新的订单)
    Summarizing,      // 正在汇总数据(汇总Metrics等)
    Completed,        // 已完成
    Failed,           // 执行失败
    Cancelled,        // 已取消
}

/// 保证金配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MarginConfig {
    pub leverage: f64, // 初始杠杆倍数
    pub margin_call_threshold: f64, // 保证金追缴阈值(如果保证金低于该值, 则需要保证金追缴)
}

/// 手续费配置
/// 手续费率是一个百分比, 例如0.001表示0.1%
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FeeConfig {
    pub bi_fee_rate: f64,     // 双边手续费率
    pub open_fee_rate: f64,   // 开仓手续费率
    pub close_fee_rate: f64,  // 平仓手续费率
}

/// 市场模拟配置
/// 
/// 关于时间倍率，用于模拟不同速度的市场(1.0表示正常速度, 如果订阅的是TICK传输上限大概为1e5), 
/// 该倍率和该Stage的最高频订阅会直接影响丢包率, 比如TICK(500ms)级别数据在10_000倍下是50us一次传输, 要求客户端能处理可能的丢包情况
/// 但是BAR(1min)在该倍率下是6ms一次传输, 丢包率会大大降低
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MarketSimConfig {
    pub time_multiplier: f64,        // 时间倍率(1.0表示正常速度, 10.0表示10倍速)
    pub liquidity_repair: f64,       // 流动性修复参数(1.0表示完全根据数据, 0.0表示不修复)
    pub trade_lag_sec: f64,          // 交易延迟参数(单位为秒, 0.0表示无延迟)
    pub data_source: Option<String>, // 数据源(如果是模拟数据, 则为None)
    pub simulate_start_us: i64,      // 模拟市场开始时间(单位为us)
    pub simulate_end_us: i64,        // 模拟市场结束时间(单位为us)
}

#[derive(Debug, Clone, Serialize, Deserialize)]
/// StageInfo DTO, 用于描述一个交易撮合Stage的状态和配置
pub struct StageInfo {
    pub id: u64,                      // Stage的唯一标识符, 实时环境时ID=0
    pub stage_type: StageType,        // Stage的类型
    pub name: String,                 // Stage的名称
    pub description: String,          // Stage的描述信息
    pub phase: StagePhase,            // 当前阶段
    pub time_unit_us: u64,            // 时间单位(单位为微秒, 轮询根据)
    pub margin: Option<MarginConfig>, // 保证金配置
    pub fee: Option<FeeConfig>,       // 手续费配置
    pub market_sim: Option<MarketSimConfig>, // 市场模拟配置
    pub created_at_us: i64,           // 创建时间(i64用于传输)
}

impl PartialEq for StageInfo {
    fn eq(&self, other: &Self) -> bool {
        self.id == other.id 
    }
}

impl Hash for StageInfo {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.id.hash(state); 
    }
}